// import 'dart:async';

// import 'package:flutter/foundation.dart';
// import 'package:flutter/material.dart';

// class CustomBanner extends StatefulWidget {
//   CustomBanner({
//     required this.items,
//     this.height = 300,
//     this.aspectRatio = 16 / 9,
//     this.viewportFraction = 0.8,
//     this.initialPage = 0,
//     int realPage = 10000,
//     this.enableInfiniteScroll = true,
//     this.reverse = false,
//     this.autoPlay = false,
//     this.autoPlayInterval = const Duration(seconds: 4),
//     this.autoPlayAnimationDuration = const Duration(milliseconds: 800),
//     this.autoPlayCurve = Curves.fastOutSlowIn,
//     required this.pauseAutoPlayOnTouch,
//     this.enlargeCenterPage = false,
//     required this.onPageChanged,
//     required this.scrollPhysics,
//     this.scrollDirection = Axis.horizontal,
//   }) : this.realPage = enableInfiniteScroll
//            ? realPage + initialPage
//            : initialPage,
//        this.itemCount = items.length,
//        this.itemBuilder = null,
//        this.pageController = PageController(
//          viewportFraction: viewportFraction,
//          initialPage: enableInfiniteScroll
//              ? realPage + initialPage
//              : initialPage,
//        );

//   /// The on demand item builder constructor
//   CustomBanner.builder({
//     @required this.itemCount,
//     @required this.itemBuilder,
//     this.height,
//     this.aspectRatio: 16 / 9,
//     this.viewportFraction: 0.8,
//     this.initialPage: 0,
//     int realPage: 10000,
//     this.enableInfiniteScroll: true,
//     this.reverse: false,
//     this.autoPlay: false,
//     this.autoPlayInterval: const Duration(seconds: 4),
//     this.autoPlayAnimationDuration = const Duration(milliseconds: 800),
//     this.autoPlayCurve: Curves.fastOutSlowIn,
//     this.pauseAutoPlayOnTouch,
//     this.enlargeCenterPage = false,
//     this.onPageChanged,
//     this.scrollPhysics,
//     this.scrollDirection: Axis.horizontal,
//   }) : this.realPage = enableInfiniteScroll
//            ? realPage + initialPage
//            : initialPage,
//        this.items = null,
//        this.pageController = PageController(
//          viewportFraction: viewportFraction,
//          initialPage: enableInfiniteScroll
//              ? realPage + initialPage
//              : initialPage,
//        );

//   /// The widgets to be shown in the carousel of default constructor
//   final List<Widget> items;

//   /// The widget item builder that will be used to build item on demand
//   final IndexedWidgetBuilder itemBuilder;

//   /// The widgets count that should be shown at carousel
//   final int itemCount;

//   /// Set carousel height and overrides any existing [aspectRatio].
//   final double height;

//   /// Aspect ratio is used if no height have been declared.
//   ///
//   /// Defaults to 16:9 aspect ratio.
//   final double aspectRatio;

//   /// The fraction of the viewport that each page should occupy.
//   ///
//   /// Defaults to 0.8, which means each page fills 80% of the carousel.
//   final num viewportFraction;

//   /// The initial page to show when first creating the [CarouselSlider].
//   ///
//   /// Defaults to 0.
//   final num initialPage;

//   /// The actual index of the [PageView].
//   ///
//   /// This value can be ignored unless you know the carousel will be scrolled
//   /// backwards more then 10000 pages.
//   /// Defaults to 10000 to simulate infinite backwards scrolling.
//   final num realPage;

//   ///Determines if carousel should loop infinitely or be limited to item length.
//   ///
//   ///Defaults to true, i.e. infinite loop.
//   final bool enableInfiniteScroll;

//   /// Reverse the order of items if set to true.
//   ///
//   /// Defaults to false.
//   final bool reverse;

//   /// Enables auto play, sliding one page at a time.
//   ///
//   /// Use [autoPlayInterval] to determent the frequency of slides.
//   /// Defaults to false.
//   final bool autoPlay;

//   /// Sets Duration to determent the frequency of slides when
//   ///
//   /// [autoPlay] is set to true.
//   /// Defaults to 4 seconds.
//   final Duration autoPlayInterval;

//   /// The animation duration between two transitioning pages while in auto playback.
//   ///
//   /// Defaults to 800 ms.
//   final Duration autoPlayAnimationDuration;

//   /// Determines the animation curve physics.
//   ///
//   /// Defaults to [Curves.fastOutSlowIn].
//   final Curve autoPlayCurve;

//   /// Sets a timer on touch detected that pause the auto play with
//   /// the given [Duration].
//   ///
//   /// Touch Detection is only active if [autoPlay] is true.
//   final Duration pauseAutoPlayOnTouch;

//   /// Determines if current page should be larger then the side images,
//   /// creating a feeling of depth in the carousel.
//   ///
//   /// Defaults to false.
//   final bool enlargeCenterPage;

//   /// The axis along which the page view scrolls.
//   ///
//   /// Defaults to [Axis.horizontal].
//   final Axis scrollDirection;

//   /// Called whenever the page in the center of the viewport changes.
//   final Function(int index) onPageChanged;

//   /// How the carousel should respond to user input.
//   ///
//   /// For example, determines how the items continues to animate after the
//   /// user stops dragging the page view.
//   ///
//   /// The physics are modified to snap to page boundaries using
//   /// [PageScrollPhysics] prior to being used.
//   ///
//   /// Defaults to matching platform conventions.
//   final ScrollPhysics scrollPhysics;

//   /// [pageController] is created using the properties passed to the constructor
//   /// and can be used to control the [PageView] it is passed to.
//   final PageController pageController;

//   /// Animates the controlled [CarouselSlider] to the next page.
//   ///
//   /// The animation lasts for the given duration and follows the given curve.
//   /// The returned [Future] resolves when the animation completes.
//   Future<void> nextPage({Duration duration, Curve curve}) {
//     return pageController.nextPage(duration: duration, curve: curve);
//   }

//   /// Animates the controlled [CarouselSlider] to the previous page.
//   ///
//   /// The animation lasts for the given duration and follows the given curve.
//   /// The returned [Future] resolves when the animation completes.
//   Future<void> previousPage({Duration duration, Curve curve}) {
//     return pageController.previousPage(duration: duration, curve: curve);
//   }

//   /// Changes which page is displayed in the controlled [CarouselSlider].
//   ///
//   /// Jumps the page position from its current value to the given value,
//   /// without animation, and without checking if the new value is in range.
//   void jumpToPage(int page) {
//     final index = _getRealIndex(
//       pageController.page.toInt(),
//       realPage - initialPage,
//       itemCount,
//     );
//     return pageController.jumpToPage(
//       pageController.page.toInt() + page - index,
//     );
//   }

//   /// Animates the controlled [CarouselSlider] from the current page to the given page.
//   ///
//   /// The animation lasts for the given duration and follows the given curve.
//   /// The returned [Future] resolves when the animation completes.
//   Future<void> animateToPage(int page, {Duration duration, Curve curve}) {
//     final index = _getRealIndex(
//       pageController.page.toInt(),
//       realPage - initialPage,
//       itemCount,
//     );
//     return pageController.animateToPage(
//       pageController.page.toInt() + page - index,
//       duration: duration,
//       curve: curve,
//     );
//   }

//   @override
//   _CarouselSliderState createState() => _CarouselSliderState();
// }

// class _CarouselSliderState extends State<CustomBanner>
//     with TickerProviderStateMixin {
//   Timer timer;

//   @override
//   void initState() {
//     super.initState();
//     timer = getTimer();
//   }

//   Timer getTimer() {
//     return widget.autoPlay
//         ? Timer.periodic(widget.autoPlayInterval, (_) {
//             widget.pageController.nextPage(
//               duration: widget.autoPlayAnimationDuration,
//               curve: widget.autoPlayCurve,
//             );
//           })
//         : null;
//   }

//   void pauseOnTouch() {
//     timer.cancel();
//     timer = Timer(widget.pauseAutoPlayOnTouch, () {
//       timer = getTimer();
//     });
//   }

//   Widget getWrapper(Widget child) {
//     if (widget.height != null) {
//       final Widget wrapper = Container(height: widget.height, child: child);
//       return widget.autoPlay && widget.pauseAutoPlayOnTouch != null
//           ? addGestureDetection(wrapper)
//           : wrapper;
//     } else {
//       final Widget wrapper = AspectRatio(
//         aspectRatio: widget.aspectRatio,
//         child: child,
//       );
//       return widget.autoPlay && widget.pauseAutoPlayOnTouch != null
//           ? addGestureDetection(wrapper)
//           : wrapper;
//     }
//   }

//   Widget addGestureDetection(Widget child) =>
//       GestureDetector(onPanDown: (_) => pauseOnTouch(), child: child);

//   @override
//   void dispose() {
//     super.dispose();
//     timer?.cancel();
//   }

//   @override
//   Widget build(BuildContext context) {
//     return getWrapper(
//       PageView.builder(
//         physics: widget.scrollPhysics,
//         scrollDirection: widget.scrollDirection,
//         controller: widget.pageController,
//         reverse: widget.reverse,
//         itemCount: widget.enableInfiniteScroll ? null : widget.itemCount,
//         onPageChanged: (int index) {
//           int currentPage = _getRealIndex(
//             index + widget.initialPage,
//             widget.realPage,
//             widget.itemCount,
//           );
//           if (widget.onPageChanged != null) {
//             widget.onPageChanged(currentPage);
//           }
//         },
//         itemBuilder: (BuildContext context, int i) {
//           final int index = _getRealIndex(
//             i + widget.initialPage,
//             widget.realPage,
//             widget.itemCount,
//           );

//           return AnimatedBuilder(
//             animation: widget.pageController,
//             child: (widget.items != null)
//                 ? widget.items[index]
//                 : widget.itemBuilder(context, index),
//             builder: (BuildContext context, child) {
//               // on the first render, the pageController.page is null,
//               // this is a dirty hack
//               if (widget.pageController.position.minScrollExtent == null ||
//                   widget.pageController.position.maxScrollExtent == null) {
//                 Future.delayed(Duration(microseconds: 1), () {
//                   if (this.mounted) {
//                     setState(() {});
//                   }
//                 });
//                 return Container();
//               }
//               double value = widget.pageController.page - i;
//               value = (1 - (value.abs() * 0.3)).clamp(0.0, 1.0);

//               final double height =
//                   widget.height ??
//                   MediaQuery.of(context).size.width * (1 / widget.aspectRatio);
//               final double distortionValue = widget.enlargeCenterPage
//                   ? Curves.easeOut.transform(value)
//                   : 1.0;

//               if (widget.scrollDirection == Axis.horizontal) {
//                 return Center(
//                   child: SizedBox(
//                     height: distortionValue * height,
//                     child: child,
//                   ),
//                 );
//               } else {
//                 return Center(
//                   child: SizedBox(
//                     width: distortionValue * MediaQuery.of(context).size.width,
//                     child: child,
//                   ),
//                 );
//               }
//             },
//           );
//         },
//       ),
//     );
//   }
// }

// /// Converts an index of a set size to the corresponding index of a collection of another size
// /// as if they were circular.
// ///
// /// Takes a [position] from collection Foo, a [base] from where Foo's index originated
// /// and the [length] of a second collection Baa, for which the correlating index is sought.
// ///
// /// For example; We have a Carousel of 10000(simulating infinity) but only 6 images.
// /// We need to repeat the images to give the illusion of a never ending stream.
// /// By calling _getRealIndex with position and base we get an offset.
// /// This offset modulo our length, 6, will return a number between 0 and 5, which represent the image
// /// to be placed in the given position.
// int _getRealIndex(int position, int base, int length) {
//   final int offset = position - base;
//   return _remainder(offset, length);
// }

// /// Returns the remainder of the modulo operation [input] % [source], and adjust it for
// /// negative values.
// int _remainder(int input, int source) {
//   if (source == 0) return 0;
//   final int result = input % source;
//   return result < 0 ? source + result : result;
// }
